using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Security.Principal;
using JSC.Portal.Entities.Interfaces;

namespace JSC.Portal.Entities
{
    public partial class PortalPage : DescriptiveEntity, ITracked, IValid, IComposite<PortalPage>, IMovable
	{
        public override bool CanDelete
        {
            get
            {
                return base.CanDelete && Sections.Count == 0 && ChildPages.Count == 0;
            }
        }

		public bool IsValid
        {
            get 
            {
                return (this.ValidTill.HasValue)
                    ? (ValidTill.Value > DateTime.Now)
                    : true;
            }
        }

		/// <summary>
		/// Property Level (int)
		/// </summary>
		public virtual int Level
		{
			get
			{
				int level = 0;
				PortalPage parentPage = Parent;
				while (parentPage != null)
				{
					parentPage = parentPage.Parent;
					level++;
				}
				return level;
			}
		}

        public bool HasRole(Role role)
		{
            return (PagePermissions.Count(ppp => ppp.Role.RoleEnum == role.RoleEnum) > 0);
		}

        public bool EditAllowed(Role role)
        {
            return EditAllowed(role.RoleEnum);
        }

        public bool EditAllowed(Roles role)
        {
            return (PagePermissions.Count(ppp => ppp.EditAllowed && ppp.Role.RoleEnum == role) > 0);
        }

        public bool ViewAllowed(Role role)
        {
            return ViewAllowed(role.RoleEnum);
        }

        public bool ViewAllowed(Roles role)
        {
            return (PagePermissions.Count(ppp => ppp.ViewAllowed && ppp.Role.RoleEnum == role) > 0);
        }

        public PortalPagePermission GetPermission(Role role)
        {
            return GetPermission(role.RoleEnum);
        }

        public PortalPagePermission GetPermission(Roles role)
        {
            return PagePermissions.SingleOrDefault(ppp => ppp.Role.RoleEnum == role);
        }

		public void SetNewFriendlyUrl()
		{
			string prefix = string.Empty;
			if (Parent != null)
			{
				prefix += Parent.FriendlyURL;
			}
            // Substitute spaces
            string tempName = Regex.Replace(Name.Trim(), "\\s", "-");
            // Substitute points
            tempName = tempName.Replace('.', '_');
            // Substitute slash
            tempName = tempName.Replace('/', '_');
            // Substitute ampersand
            tempName = tempName.Replace('&', '-');
            // Substitute backslash
            tempName = tempName.Replace('\\', '_');
            			
			FriendlyURL = System.Web.HttpUtility.UrlPathEncode(string.IsNullOrEmpty(prefix) ? tempName.ToLower() : prefix + "/" + tempName.ToLower());
		}

        /// <summary>
        /// Indicates if viewing of the node is allowed. Anonymous users get a special treatment because we
        /// can't check their rights because they are no full-blown Portal users (not authenticated).
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public virtual bool ViewAllowed(IIdentity user)
        {
            PortalUser portalUser = user as PortalUser;
            if (AnonymousViewAllowed)
            {
                return true;
            }
            else if (portalUser != null)
            {
                return portalUser.CanView(this);
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Can the PortalPage be viewed by anonymous users?
        /// </summary>
        public virtual bool AnonymousViewAllowed
        {
            get { return (PagePermissions.Count(ppp => ppp.Role.RoleEnum == Roles.Anonymous) > 0); }
        }

        public bool CanMove()
        {
            return CanMoveDown() || CanMoveUp() || CanMoveRight() || CanMoveLeft();
        }

        public bool CanMoveUp()
        {
            return Id > 0 && Position > 0;
        }

        public bool CanMoveDown()
        {
            return ((Parent != null) && (Position != Parent.ChildPages.Count - 1) && Id != -1);
        }

        public bool CanMoveLeft()
        {
            return (Level > 1 && Id != -1);
        }

        public bool CanMoveRight()
        {
            return (Position > 0 && Level > 0);
        }

        public PortalPage GetRootPage()
        {
            PortalPage root = this;
            while (root.Parent != null && root.Parent.Language == root.Language)
                root = root.Parent;
            return root;
        }

        #region IComposite<PortalPage> Members

        public IList<PortalPage> Children
        {
            get { return ChildPages; }
        }

        #endregion
    }
}